#!/usr/bin/python
#  -*- coding:utf-8 -*-

import numpy as np
import math
import matplotlib as mpl
import matplotlib.pyplot as plt
# import seaborn


# e^x 的Taylor级数展开
def calc_e_small(x):
    n = 10
    f = np.arange(1, n+1).cumprod()#生成从1到n的累乘数组，即[1!, 2!, 3!, ..., n!]，用于计算泰勒级数的分母（阶乘）
    b = np.array([x]*n).cumprod()#生成n个x的累乘数组，即[x¹, x², x³, ..., xⁿ]，用于计算泰勒级数的分子（x的幂次）
    return np.sum(b / f) + 1

"""
1.处理负数：e^(-x) = 1/e^x
2.分解x：x = a*ln2 + b，其中a为整数，b为0到1之间的数
"""
def calc_e(x):
    reverse = False
    if x < 0:   # 处理负数
        x = -x
        reverse = True
    ln2 = 0.69314718055994530941723212145818
    c = x / ln2
    a = int(c+0.5)
    b = x - a*ln2
    y = (2 ** a) * calc_e_small(b)
    if reverse:
        return 1/y
    return y


if __name__ == "__main__":
    t1 = np.linspace(-2, 0, 10, endpoint=False)#创建了一个从-2开始，到0结束（但不包含0<endpoint=False>），共10个等间距数值的一维数组
    t2 = np.linspace(0, 4, 20)
    t = np.concatenate((t1, t2))
    print(t)     # 横轴数据
    y = np.empty_like(t)# 创建一个和t具有相同形状和数据类型的空数组
    for i, x in enumerate(t):
        y[i] = calc_e(x)
        print('e^', x, ' = ', y[i], '(近似值)\t', math.exp(x), '(真实值)')
    plt.figure(facecolor='w')
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    plt.plot(t, y, 'r-', t, y, 'go', linewidth=2, markeredgecolor='k')
    plt.title('Taylor展式的应用 - 指数函数', fontsize=18)
    plt.xlabel('X', fontsize=15)
    plt.ylabel('exp(X)', fontsize=15)
    plt.grid(True, ls=':')
    plt.show()
